package com.example.sicnuaccountingapp.ui.statistics

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.sicnuaccountingapp.data.entity.TransactionType
import com.example.sicnuaccountingapp.data.repository.CategoryRepository
import com.example.sicnuaccountingapp.data.repository.TransactionRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import java.time.*
import java.time.temporal.ChronoUnit
import javax.inject.Inject

@HiltViewModel
class StatisticsViewModel @Inject constructor(
    private val transactionRepository: TransactionRepository,
    private val categoryRepository: CategoryRepository
) : ViewModel() {

    private val _state = MutableStateFlow<StatisticsUiState>(StatisticsUiState.Loading)
    val state: StateFlow<StatisticsUiState> = _state.asStateFlow()

    private var currentUserId: Long = -1L
    private var isMonthly = true

    fun setUserId(userId: Long) {
        currentUserId = userId
        loadStatistics()
    }

    fun setTimeRange(monthly: Boolean) {
        isMonthly = monthly
        loadStatistics()
    }

    private fun loadStatistics() {
        viewModelScope.launch {
            try {
                _state.value = StatisticsUiState.Loading

                val now = LocalDate.now()
                val (startDate, endDate) = if (isMonthly) {
                    Pair(
                        now.withDayOfMonth(1),
                        now.withDayOfMonth(now.lengthOfMonth())
                    )
                } else {
                    Pair(
                        now.withDayOfYear(1),
                        now.withDayOfYear(now.lengthOfYear())
                    )
                }

                val startTime = startDate.atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli()
                val endTime = endDate.atTime(23, 59, 59).toInstant(ZoneOffset.UTC).toEpochMilli()

                combine(
                    transactionRepository.getTransactionsByDateRange(currentUserId, startTime, endTime),
                    categoryRepository.getAllCategories(currentUserId)
                ) { transactions, categories ->
                    val totalIncome = transactions
                        .filter { it.type == TransactionType.INCOME }
                        .sumOf { it.amount }

                    val totalExpense = transactions
                        .filter { it.type == TransactionType.EXPENSE }
                        .sumOf { it.amount }

                    val expenseTransactions = transactions.filter { it.type == TransactionType.EXPENSE }
                    
                    val categoryExpenses = expenseTransactions
                        .groupBy { it.categoryId }
                        .mapNotNull { (categoryId, transactions) ->
                            val category = categories.find { it.categoryId == categoryId }
                            category?.let {
                                CategoryExpense(
                                    category = it,
                                    amount = transactions.sumOf { it.amount }
                                )
                            }
                        }
                        .sortedByDescending { it.amount }

                    StatisticsUiState.Success(
                        totalIncome = totalIncome,
                        totalExpense = totalExpense,
                        categoryExpenses = categoryExpenses,
                        dailyExpenses = expenseTransactions
                            .groupBy {
                                LocalDateTime.ofInstant(
                                    Instant.ofEpochMilli(it.date),
                                    ZoneId.systemDefault()
                                ).truncatedTo(ChronoUnit.DAYS)
                            }
                            .mapValues { it.value.sumOf { transaction -> transaction.amount } },
                        categoryPercentages = expenseTransactions
                            .groupBy { it.categoryId }
                            .mapValues { (_, transactions) ->
                                transactions.sumOf { it.amount } / totalExpense * 100
                            },
                        monthlyTrend = transactions
                            .groupBy {
                                LocalDateTime.ofInstant(
                                    Instant.ofEpochMilli(it.date),
                                    ZoneId.systemDefault()
                                ).withDayOfMonth(1)
                            }
                            .mapValues { (_, transactions) ->
                                val income = transactions
                                    .filter { it.type == TransactionType.INCOME }
                                    .sumOf { it.amount }
                                val expense = transactions
                                    .filter { it.type == TransactionType.EXPENSE }
                                    .sumOf { it.amount }
                                income to expense
                            },
                        weekdayStats = expenseTransactions
                            .groupBy {
                                LocalDateTime.ofInstant(
                                    Instant.ofEpochMilli(it.date),
                                    ZoneId.systemDefault()
                                ).dayOfWeek.value
                            }
                            .mapValues { it.value.sumOf { transaction -> transaction.amount } }
                    )
                }.collect { state ->
                    _state.value = state
                }
            } catch (e: Exception) {
                _state.value = StatisticsUiState.Error(e.message ?: "加载失败")
            }
        }
    }
} 